<template>
  <div>
    <div class="todo-container">
      <div class="todo-wrap">
          <TodoHeader @addTodo="addTodo"/>
          <TodoList :todoList="todoList"/>
          <TodoFooter :todoList="todoList" @checkAllTodo="checkAllTodo" @deleteAllTodo="deleteAllTodo"/>
      </div>
    </div>
  </div>
</template>

<script>
  // 引入Header组件
  import TodoHeader from './components/TodoHeader.vue'
  // 引入List组件
  import TodoList from './components/TodoList.vue'
  // 引入Footer组件
  import TodoFooter from './components/TodoFooter.vue'

  export default {
      name:'App',
      components:{TodoHeader,TodoList,TodoFooter},
      data(){
        return {
            // 采用浏览器本地存储机制获取todoList中的数据
            // 将本地存储中的JOSN字符串数据解析成对象的形式以便展示
            todoList:JSON.parse(localStorage.getItem("todoList")) || []
        }
      },
      methods:{
        /*
          【组件间通信方式：当子组件要传递参数给父组件时】
            定义一个方法，当App渲染子组件<todoHeader/>时，将这个方法传递过去
            子组件通过props接收当前方法，子组件再通过this.addTodo调用这个方法时，就可以将参数传递给父组件（App）。
        */
        // 添加一个todo
        addTodo(todoObj){
          //接收到子组件发送过来的todo对象并添加到数组第一位
          this.todoList.unshift(todoObj);
        },

        // 改变todo的状态（isFinish），勾选或者是取消勾选一个todo时
        updateTodoStatus(todoId){
          //遍历当前todoList数组
          this.todoList.forEach( todo =>{
            if(todo.todoId == todoId) todo.isFinish = !todo.isFinish; //如果遍历到id相同的todo那么取反
            })
        },

        //删除一个todo
        deleteTodo(todoId){
          //使用filter函数过滤数组，并且将过滤好的数组，重新赋值到当前页面的数组（因为filter函数产生的数据改变Vue不做渲染）
          this.todoList = this.todoList.filter(todo => todo.todoId != todoId);
        },

        //全选 or 取消全选
        checkAllTodo(status){
          this.todoList.forEach((todo)=>{
            todo.isFinish = status;
          });
        },

        //清除所有已完成的任务
        deleteAllTodo(){
          this.todoList = this.todoList.filter((todo)=>{
            return !todo.isFinish;
          })
        }
      },
      watch:{
        todoList:{
          deep:true, //开启深度监视，可监视到对象下所有属性的值变化，默认值为false
          handler(value){
            // 采用监听的方式监控todoList数据的改变情况，当添加一个任务时，就调用setItem()方法将数据存储到本地存储中
            // stringify()：将对象转化成JSON字符串的数据形式以便存储
            localStorage.setItem('todoList',JSON.stringify(value))
          }
        }
      },
      // 初始化挂载前
      mounted(){
        this.$bus.$on('updateTodoStatus',this.updateTodoStatus);
        this.$bus.$on('deleteTodo',this.deleteTodo);
      },
      // 实例销毁前
      beforeDestroy(){
        this.$bus.$off('updateTodoStatus');
        this.$bus.$off('deleteTodo');
      }
  }
</script>

<style>
  /*base*/
  body {
    background: #fff;
  }

  .btn {
    display: inline-block;
    padding: 4px 12px;
    margin-bottom: 0;
    font-size: 14px;
    line-height: 20px;
    text-align: center;
    vertical-align: middle;
    cursor: pointer;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
    border-radius: 4px;
  }

  .btn-danger {
    color: #fff;
    background-color: #da4f49;
    border: 1px solid #bd362f;
  }

  .btn-danger:hover {
    color: #fff;
    background-color: #bd362f;
  }

  .btn:focus {
    outline: none;
  }

  .todo-container {
    width: 600px;
    margin: 0 auto;
  }
  .todo-container .todo-wrap {
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 5px;
  }
</style>